package cn.xw.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author AnHui OuYang
 * @version 1.0
 * created at 2023-04-17 10:56
 */
@Configuration
public class RabbitMQConfig {

    //直接交换机名称
    public static final String EXCHANGE_NAME = "MsgHandleExchange";
    //队列名称
    public static final String QUEUE_NAME = "MsgHandleQueue";
    //路由key
    public static final String ROUTING_KEY = "MsgHandleKey";
    //声明死信交换机名称
    public static final String DLX_EXCHANGE = "DLXExchange";
    //声明死信队列名称
    public static final String DLX_QUEUE = "DLXQueue";
    //声明路由绑定关系 Routing Key 死信交换机到死信队列
    public static final String DLX_KEY = "DLXKey";


    //+++++++++++++++++配置了直连交换机和队列的关系

    /***
     * 一个普通的直连交换机
     * @return Exchange
     */
    @Bean("msgHandleExchange")
    public Exchange msgHandleExchange() {
        //第一种方式：使用new的方式，是什么类型交换机我们就创建什么xxxExchange
        //参数1：exchange: 交换机名称
        //参数2：durable: 是否需要持久化
        //参数3：autoDelete: 当最后一个绑定到Exchange上的队列删除后，自动删除该Exchange
        //参数4：arguments: 扩展参数，用于扩展AMQP协议定制化使用
        //Exchange directExchange = new DirectExchange(EXCHANGE_NAME,true,false);
        //当前Exchange是否用于RabbitMQ内部使用，默认为False
        //使用默认即可directExchange.isInternal();

        //第二种方式：使用Builder方式
        return ExchangeBuilder.directExchange(EXCHANGE_NAME).durable(true).build();
    }

    /***
     * 一个普通的队列
     * @return Queue
     */
    @Bean("msgHandleQueue")
    public Queue msgHandleQueue() {
        //第一种方式：使用new的方式；这种和原生创建一样
        //参数一：队列名称
        //参数二：队列里的消息是否持久化，默认消息保存在内存中，默认false
        //参数三：该队列是否只供一个消费者进行消费的独占队列，则为 true（仅限于此连接），false（默认，可以多个消费者消费）
        //参数四：是否自动删除 最后一个消费者断开连接以后 该队列是否自动删除 true 自动删除，默认false
        //参数五：构建队列的其它属性，看下面扩展参数
        //Queue queue = new Queue(QUEUE_NAME,true,false,false,null);
        //原生： channel.queueDeclare(QUEUE_NAME, true, false, false, null);

        //第二种方式：使用Builder方式
        //~~~~~~~~~~~~~~~~~~~~~~~~~~设置死信参数Start
        //绑定死信队列（参数设置）
        Map<String, Object> arguments = new HashMap<>();
        //正常队列设置死信交换机 参数key是固定值；（就是说死去的消息发送到哪个交换机）
        arguments.put("x-dead-letter-exchange", DLX_EXCHANGE);
        //正常队列设置死信交换机到死信队列绑定Routing Key 参数key是固定值（就是说死去的消息在交换机里通过什么路由发送到死信队列）
        arguments.put("x-dead-letter-routing-key", DLX_KEY);
        //设置正常队列的长度限制 为3
        //arguments.put("x-max-length",3);
        //队列设置消息过期时间 60 秒
        //arguments.put("x-message-ttl", 60 * 1000);
        //~~~~~~~~~~~~~~~~~~~~~~~~~~设置死信参数End
        return QueueBuilder.durable(QUEUE_NAME).withArguments(arguments).build();
    }

    /***
     * 队列绑定到交换机
     * @param msgHandleExchange 交换机名称
     * @param msgHandleQueue 队列名称
     * @return Binding
     */
    @Bean("queueBindDirectExchange")
    public Binding queueBindDirectExchange(@Qualifier("msgHandleExchange") Exchange msgHandleExchange,
                                           @Qualifier("msgHandleQueue") Queue msgHandleQueue) {
        return BindingBuilder.bind(msgHandleQueue).to(msgHandleExchange).with(ROUTING_KEY).noargs();
    }

    //+++++++++++++++++配置死信交换机的一系列信息

    /***
     * 死信交换机
     * @return Exchange
     */
    @Bean("DLXExchange")
    public Exchange dLXExchange() {
        return ExchangeBuilder.directExchange(DLX_EXCHANGE).durable(true).build();
    }

    /***
     * 死信队列
     * @return Queue
     */
    @Bean("DLXQueue")
    public Queue dLXQueue() {
        return QueueBuilder.durable(DLX_QUEUE).build();
    }

    /***
     * 死信交换机上面绑定死信队列
     * @return Binding
     */
    @Bean("dlxQueueBindDlxExchange")
    public Binding dlxQueueBindDlxExchange(@Qualifier("DLXExchange") Exchange dLXExchange,
                                           @Qualifier("DLXQueue") Queue dLXQueue) {
        //死信交换机上面绑定死信队列
        return BindingBuilder.bind(dLXQueue).to(dLXExchange).with(DLX_KEY).noargs();
    }
}
